package com.xcity.game.activity2.share;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;

import com.xcity.db.entity.Employee;
import com.xcity.db.entity.Mine;
import com.xcity.db.entity.Player;
import com.xcity.game.account.AccountChannel;
import com.xcity.game.activity2.share.action.QQShareAction;
import com.xcity.game.activity2.share.template.QQShareActivityTemplate;
import com.xcity.game.battle.pve.PVEManager;
import com.xcity.game.battle.pve.PVEStage;
import com.xcity.game.battle.pve.template.StagePageTemplate;
import com.xcity.game.buildv2.BuildV2;
import com.xcity.game.common.GameStaticConfig;
import com.xcity.game.common.PlayerPool;
import com.xcity.game.employee.EmployeeQuality;
import com.xcity.game.equip.Equip;
import com.xcity.game.equip.EquipQuality;
import com.xcity.game.event.GameEvents;
import com.xcity.game.peakroad.template.PeakRoadTemplate;
import com.xcity.game.rank.RankingListEnum;
import com.xcity.pomelo.push.msg.QQSharePush;
import com.xcity.util.BackDoorHandler;
import com.xcity.util.SessionUtils;

import gnu.trove.map.TByteObjectMap;
import gnu.trove.map.hash.TByteObjectHashMap;
import naga.x.App;
import naga.x.event.Event;
import naga.x.event.EventListener;
import naga.x.game.template.TemplateService;
import naga.x.net.Packet;
import naga.x.util.NumberUtils;

public class EventDispatcher implements EventListener {

	// 条件id
	public static final byte COND_QQ_SAY2 = 1; // 分享说说
	public static final byte COND_ADD_EMPLOYEE = 2; // 获得员工
	public static final byte COND_BUILDING_FINISH = 3; // 建造完成
	public static final byte COND_ADVENTURE_STEAL = 4; // 猜富豪
	public static final byte COND_ADVENTURE_ATTACK = 5; // 砸建筑
	public static final byte COND_BUILD_CAPTURE = 6; // 占领建筑
	public static final byte COND_CLIENT_ADD_SHORTCUT = 7; // 客户端添加到桌面
	public static final byte COND_EMPLOYEE_QUALITY_LEVEL_UP = 8; // 员工升品
	public static final byte COND_EMPLOYEE_STAR_LEVEL_UP = 9; // 员工升星
	public static final byte COND_PEAK_ROAD_PASS = 10; // 巅峰之路挑战胜利
	public static final byte COND_ARENA_SUCC = 11; // 竞技场胜利
	public static final byte COND_EQUIPMENT_LEVEL_UP = 12; // 奢侈品升级
	public static final byte COND_HELP_FRIEND_DEFENSE = 13; // 协助好友防守 TODO
	public static final byte COND_RANKING_UPPED = 14; // 进入排行榜名次
	public static final byte COND_MINE_TAKEN = 15; // 占矿
	public static final byte COND_PVE_PASS = 16; // 副本胜利
	
	private TByteObjectMap<List<QQShareActivityTemplate>> cond2templates;
	
	public EventDispatcher() {
		List<QQShareActivityTemplate> list = App.getApp().getServiceManager().get(TemplateService.class).getTemplatesList(QQShareActivityTemplate.class);
		cond2templates = new TByteObjectHashMap<>();
		for (int i = 0; i < list.size(); i++) {
			QQShareActivityTemplate template = list.get(i);
			byte cond = template.getConditionId();
			List<QQShareActivityTemplate> group = cond2templates.get(cond);
			if (group == null) {
				group = new ArrayList<>(1); // 目前每个条件的分享就1个
				cond2templates.put(cond, group);
			}
			group.add(template);
		}
	}
	
	@Override
	public int[] getEventTypes() {
		return new int[] {
				GameEvents.EVENT_EMPLOYEE_ADDED,
				GameEvents.EVENT_BUILDING_FINISH_V2,
				GameEvents.EVENT_ADVENTURE_STEAL,
				GameEvents.EVENT_ADVENTURE_ATTACK,
				GameEvents.EVENT_BUILDING_CAPTURE,
				GameEvents.EVENT_EMPLOYEE_QUALITY_UP,
				GameEvents.EVENT_EMPLOYEE_STAR_UP,
				GameEvents.EVENT_PEAK_ROAD_WIN,
				GameEvents.EVENT_ARENA_END,
				GameEvents.EVENT_EQUIP_ENHANCE,
				GameEvents.EVENT_RANKING_UPPED,
				GameEvents.EVENT_MINE_ATTACK_SUCC,
				GameEvents.EVENT_MINE_TAKEN,
				GameEvents.EVENT_PVE_SUCCESS,
		};
	}

	@Override
	public void handleEvent(Event event) {
		Player player = event.getParameter(0);
		if (player.getPool().getShortValue(PlayerPool.PROPERTY_GUIDE) < GameStaticConfig.fresherMaxGuide) {
			return;
		}
		AccountChannel channel = player.getAccount().getChannel();
		if (!BackDoorHandler.CHEAT_ENABLE && channel != AccountChannel.QQ_WANBA && channel != AccountChannel.QQ) {
			return;
		}
		switch (event.getType()) {
			case GameEvents.EVENT_EMPLOYEE_ADDED:
				fireEmployeeAdded(player, event.getParameter(1));
				break;
			case GameEvents.EVENT_BUILDING_FINISH_V2:
				fireBuildingFinish(player, event.getParameter(1));
				break;
			case GameEvents.EVENT_ADVENTURE_STEAL:
				fireSteal(player, event.getParameter(3), event.getParameter(1), event.getParameter(2));
				break;
			case GameEvents.EVENT_ADVENTURE_ATTACK:
				fireAttack(player, event.getParameter(1), event.getParameter(2));
				break;
			case GameEvents.EVENT_BUILDING_CAPTURE:
				fireCapture(player, event.getParameter(1));
				break;
			case GameEvents.EVENT_EMPLOYEE_QUALITY_UP:
				fireEmployeeQualityLevelUp(player, event.getParameter(1));
				break;
			case GameEvents.EVENT_EMPLOYEE_STAR_UP:
				fireEmployeeStarLevelUp(player, event.getParameter(1));
				break;
			case GameEvents.EVENT_PEAK_ROAD_WIN:
				firePeakRoadPassed(player, event.getParameter(1));
				break;
			case GameEvents.EVENT_ARENA_END:
				fireArenaEnded(player, event.getParameter(2));
				break;
			case GameEvents.EVENT_EQUIP_ENHANCE:
				fireEquipmentEnhanced(player, event.getParameter(1));
				break;
			case GameEvents.EVENT_RANKING_UPPED:
				fireRankingUpped(player, event.getParameter(1), event.getParameter(2));
				break;
			case GameEvents.EVENT_MINE_ATTACK_SUCC:
				fireMineTaken(player, event.getParameter(2));
				break;
			case GameEvents.EVENT_MINE_TAKEN:
				fireMineTaken(player, event.getParameter(1));
				break;
			case GameEvents.EVENT_PVE_SUCCESS:
				firePvePass(player, event.getParameter(1), event.getParameter(4));
				break;
		}
	}
	
	private void fireEmployeeAdded(final Player player, final Employee employee) {
		List<QQShareActivityTemplate> templates = cond2templates.get(COND_ADD_EMPLOYEE);
		DispatchAdapter adapter = new DispatchAdapter() {
			@Override
			public boolean validate(QQShareActivityTemplate template) {
				EmployeeQuality quality = EmployeeQuality.forName(template.getCondition(0));
				if (quality == null) {
					quality = EmployeeQuality.D;
				}
				return employee.getTemplate().getQuality().ordinal() >= quality.ordinal();
			}
			@Override
			public QQSharePush doFilter(QQSharePush packet) {
				packet.name = MessageFormat.format(packet.name, employee.getName());
				return packet;
			}
		};
		doDispatch(player, templates, adapter);
		
	}
	
	private void fireBuildingFinish(Player player, BuildV2 building) {
		PacketFilter<QQSharePush> filter = new PacketFilter<QQSharePush>() {
			@Override
			public QQSharePush doFilter(QQSharePush packet) {
				packet.name = MessageFormat.format(packet.name, building.getTemplate().getName());
				return packet;
			}
		};
		doDispatch(player, cond2templates.get(COND_BUILDING_FINISH), null, filter);
	}
	
	private void fireSteal(final Player player, final Player target, final int gold, final boolean bingo) {
		if (bingo) {
			PacketFilter<QQSharePush> filter = new PacketFilter<QQSharePush>() {
				@Override
				public QQSharePush doFilter(QQSharePush packet) {
					packet.name = MessageFormat.format(packet.name, target.getName(), String.valueOf(gold));
					return packet;
				}
			};
			doDispatch(player, cond2templates.get(COND_ADVENTURE_STEAL), null, filter);
		}
	}
	
	private void fireAttack(final Player player, final Player target, final BuildV2 building) {
		PacketFilter<QQSharePush> filter = new PacketFilter<QQSharePush>() {
			@Override
			public QQSharePush doFilter(QQSharePush packet) {
				packet.name = MessageFormat.format(packet.name, target.getName(), building.getTemplate().getName());
				return packet;
			}
		};
		doDispatch(player, cond2templates.get(COND_ADVENTURE_ATTACK), null, filter);
	}

	private void fireCapture(final Player player, final BuildV2 building) {
		PacketFilter<QQSharePush> filter = new PacketFilter<QQSharePush>() {
			@Override
			public QQSharePush doFilter(QQSharePush packet) {
				Player target = building.getVm().getOwner();
				packet.name = MessageFormat.format(packet.name, target.getName(), building.getTemplate().getName());
				return packet;
			}
		};
		doDispatch(player, cond2templates.get(COND_BUILD_CAPTURE), null, filter);
	}
	
	private void fireEmployeeQualityLevelUp(final Player player, final Employee employee) {
		DispatchAdapter adapter = new DispatchAdapter() {
			@Override
			public boolean validate(QQShareActivityTemplate template) {
				EmployeeQuality quality = EmployeeQuality.forName(template.getCondition(0));
				if (quality == null) {
					quality = EmployeeQuality.D;
				}
				int qualityLvl = NumberUtils.parseInt(template.getCondition(1));
				return employee.getTemplate().getQuality().ordinal() >= quality.ordinal()
						&& employee.getQualityLvl() >= qualityLvl;
			}
			@Override
			public QQSharePush doFilter(QQSharePush packet) {
				packet.name = MessageFormat.format(packet.name, employee.getName(), String.valueOf(employee.getQualityLvl()));
				return packet;
			}
		};
		List<QQShareActivityTemplate> templates = cond2templates.get(COND_EMPLOYEE_QUALITY_LEVEL_UP);
		doDispatch(player, templates, adapter);
	}
	
	private void fireEmployeeStarLevelUp(final Player player, final Employee employee) {
		DispatchAdapter adapter = new DispatchAdapter() {
			@Override
			public boolean validate(QQShareActivityTemplate template) {
				EmployeeQuality quality = EmployeeQuality.forName(template.getCondition(0));
				if (quality == null) {
					quality = EmployeeQuality.D;
				}
				int starLvl = NumberUtils.parseInt(template.getCondition(1));
				return employee.getTemplate().getQuality().ordinal() >= quality.ordinal()
						&& employee.getStarLvl() >= starLvl;
			}
			@Override
			public QQSharePush doFilter(QQSharePush packet) {
				packet.name = MessageFormat.format(packet.name, employee.getName(), String.valueOf(employee.getStarLvl()));
				return packet;
			}
		};
		List<QQShareActivityTemplate> templates = cond2templates.get(COND_EMPLOYEE_STAR_LEVEL_UP);
		doDispatch(player, templates, adapter);
	}
	
	private void firePeakRoadPassed(final Player player, final PeakRoadTemplate instanceTemplate) {
		if (instanceTemplate == null) { // 扫荡不算
			return;
		}
		DispatchAdapter adapter = new DispatchAdapter() {
			@Override
			public boolean validate(QQShareActivityTemplate template) {
				int floor = NumberUtils.parseInt(template.getCondition(0));
				return instanceTemplate.getId() >= floor;
			}
			@Override
			public QQSharePush doFilter(QQSharePush packet) {
				packet.name = MessageFormat.format(packet.name, String.valueOf(instanceTemplate.getId()));
				return packet;
			}
		};
		List<QQShareActivityTemplate> templates = cond2templates.get(COND_PEAK_ROAD_PASS);
		doDispatch(player, templates, adapter);
	}
	
	private void fireArenaEnded(Player player, boolean succ) {
		if (succ) {
			List<QQShareActivityTemplate> templates = cond2templates.get(COND_ARENA_SUCC);
			doDispatch(player, templates);
		}
	}
	
	private void fireEquipmentEnhanced(final Player player, final Equip equipment) {
		DispatchAdapter adapter = new DispatchAdapter() {
			@Override
			public boolean validate(QQShareActivityTemplate template) {
				EquipQuality quality = EquipQuality.forName(template.getCondition(0));
				if (quality == null) {
					quality = EquipQuality.D;
				}
				int level = NumberUtils.parseInt(template.getCondition(1));
				return equipment.getQuality().ordinal() >= quality.ordinal() && equipment.getLevel() >= level;
			}
			@Override
			public QQSharePush doFilter(QQSharePush packet) {
				packet.name = MessageFormat.format(packet.name, equipment.getTemplate().getName(), String.valueOf(equipment.getLevel()));
				return packet;
			}
		};
		List<QQShareActivityTemplate> templates = cond2templates.get(COND_EQUIPMENT_LEVEL_UP);
		doDispatch(player, templates, adapter);
	}
	
	private void fireRankingUpped(final Player player, final int ranking, final byte type) {
		DispatchAdapter adapter = new DispatchAdapter() {
			@Override
			public boolean validate(QQShareActivityTemplate template) {
				RankingListEnum rle = RankingListEnum.forType(NumberUtils.parseByte(template.getCondition(0)));
				if (type != rle.instance.getType()) {
					return false;
				}
				int rankingCond = NumberUtils.parseInt(template.getCondition(1));
				return ranking <= rankingCond;
			}
			@Override
			public QQSharePush doFilter(QQSharePush packet) {
				packet.name = MessageFormat.format(packet.name, RankingListEnum.forType(type).name, String.valueOf(ranking));
				return packet;
			}
		};
		List<QQShareActivityTemplate> templates = cond2templates.get(COND_RANKING_UPPED);
		doDispatch(player, templates, adapter);
	}
	
	private void fireMineTaken(final Player player, final Mine mine) {
		List<QQShareActivityTemplate> templates = cond2templates.get(COND_MINE_TAKEN);
		doDispatch(player, templates);
	}
	
	private void firePvePass(final Player player, final PVEStage stage, boolean isFirstPass) {
		if (isFirstPass) {
			DispatchAdapter adapter = new DispatchAdapter() {
				@Override
				public boolean validate(QQShareActivityTemplate template) {
					int type = stage.getTemplate().getType() == PVEManager.STAGE_TYPE_HERO ? 1 : 0;
					List<PVEStage> list = player.getPveStages().getStages(stage.getTemplate().getPage() - 1, type);
					return list.get(list.size() - 1).getId() == stage.getId();
				}
				@Override
				public QQSharePush doFilter(QQSharePush packet) {
					String type = stage.getTemplate().getType() == PVEManager.STAGE_TYPE_HERO ? "精英" : "普通";
					String pageName = App.getApp().getServiceManager().get(TemplateService.class).get(StagePageTemplate.class, stage.getTemplate().getPage()).getPageName();
					packet.name = MessageFormat.format(packet.name, type, pageName);
					return packet;
				}
			};
			List<QQShareActivityTemplate> templates = cond2templates.get(COND_PVE_PASS);
			doDispatch(player, templates, adapter);
		}
	}
	
	
	
	private void doDispatch(Player player, List<QQShareActivityTemplate> templates) {
		doDispatch(player, templates, null);
	}
	
	private void doDispatch(Player player, List<QQShareActivityTemplate> templates, DispatchValidator validator) {
		doDispatch(player, templates, validator, null);
	}
	
	private void doDispatch(Player player, List<QQShareActivityTemplate> templates, DispatchAdapter adapter) {
		doDispatch(player, templates, adapter, adapter);
	}
	
	private void doDispatch(Player player, List<QQShareActivityTemplate> templates, DispatchValidator validator, PacketFilter<QQSharePush> filter) {
		if (templates == null)
			return;
		for (int i = 0; i < templates.size(); i++) {
			QQShareActivityTemplate template = templates.get(i);
			String sessKey = SessionUtils.QQ_SHARE_PREFIX + template.getId();
			Integer n = player.getSession().getAttribute(sessKey);
			if (n != null && n.intValue() > 2) { // 至少已经提示过3次后，则不再提示
				continue;
			}
			if (player.getLevel() >= template.getLevelLimit()
					&& QQShareAction.getState(player, template) == ShareAction.STATE_CAN_REWARD
					&& (validator == null || validator.validate(template))) {
				QQSharePush packet = new QQSharePush(template, player, ShareAction.STATE_CAN_NOT_REWARD);
				player.send(filter != null ? filter.doFilter(packet) : packet);
				player.getSession().setAttribute(sessKey, n != null ? n + 1 : 1);
			}
		}
	}
	
	interface DispatchValidator {
		boolean validate(QQShareActivityTemplate template);
	}
	
	interface PacketFilter<P extends Packet> {
		P doFilter(P packet);
	}
	
	static abstract class DispatchAdapter implements DispatchValidator, PacketFilter<QQSharePush> {
		@Override
		public QQSharePush doFilter(QQSharePush packet) {
			return packet;
		}
		@Override
		public boolean validate(QQShareActivityTemplate template) {
			return false;
		}
	}
	
}
